
local raw = ...
local raw_open = raw.open_font
local image_meta = raw.registry["image meta"]
local raw_render_solid = raw.render_solid

local io_open = io.open
local pcall = pcall
local setmetatable = raw.setmetatable
local tonumber = tonumber
local error = error

local function constant(value)
    return function()  return value;  end
end

local font_meta do
    local font_getters = {
        solid = constant(function(...)
            local success,result = pcall(raw_render_solid, ...)
            if not success then
                error(result,2)
            end
            return setmetatable(result, image_meta)
        end);
		bold = raw.get_bold;
		italics = raw.get_italic;
		underline = raw.get_underline;
		underlined = raw.get_underline;
		height = raw.get_height;
		ascent = raw.get_ascent;
		descent = raw.get_descent;
		lineskip = raw.get_lineskip;
		monospace = raw.get_monospace;
		title = raw.get_title;
		charmetrics = constant(raw.charmetrics);
		textsize = constant(raw.textsize);
    }
    
    local font_setters = {
		bold = raw.set_bold;
		italic = raw.set_italic;
		italics = raw.set_italic;
		underline = raw.set_underline;
		underlined = raw.get_underline;
    }
    
    font_meta = {
        __gc = raw.destroy_font;
        __tostring = raw.font_summary;
        __index = function(self,key)
            local getter = font_getters[key]
            if getter then
                return getter(self)
            end
            error('attempt to get nonexistent field of font struct object',2)
        end;
        __newindex = function(self,key,value)
            local setter = font_setters[key]
            if setter then
                return setter(self,value)
            elseif getters[key] then
                error('attempt to set a read-only field',2)
            end
            error('attempt to set nonexistent field of font struct object',2)
        end;
    }
end

return {
    resource = function(res, index, size)
        if not size then
            index,size = 0,index
        end
        size = tonumber(size)
        if not size then
            return error('expecting a size parameter',2)
        end
        local success,result = pcall(raw_open, res, size, index)
        if not success then
            return error(result,2)
        end
        return setmetatable(result, font_meta)
    end;
}
